/*  
    Copyright 2010 Mike Eheler <mike.eheler@gmail.com>

    This file is part of Four Falling Blocks Puzzle Game.

    Four Falling Blocks Puzzle Game is free software: you can
	redistribute it and/or modify it under the terms of the GNU General
	Public License as published by the Free Software Foundation, either
	version 3 of the License, or (at your option) any later version.

    Four Falling Blocks Puzzle Game is distributed in the hope that it
	will be useful, but WITHOUT ANY WARRANTY; without even the implied
	warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Four Falling Blocks Puzzle Game.
	
	If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>

#include "fbmainwindow.moh"
#include "fbdialogs.moh"

#include "../../debug_console.h"
#include "../../../tmp/uic/ui_scores.h"
#include "../../../tmp/uic/ui_highscore.h"

#include "../../game.h"

FBMainWindow::FBMainWindow( QWidget * parent )
  : QMainWindow( parent ),
    mGame( 0 )
{
	setupUi( this );

	mTimer = new QTimer( this );

	connect( mTimer, SIGNAL(timeout()), this, SLOT(tick()) );

	// hrm.. 
	mGame = Game::instance();

	preview_0->setPiece( 0 );
	preview_1->setPiece( 1 );
	preview_2->setPiece( 2 );
	preview_3->setPiece( 3 );
	preview_4->setPiece( 4 );
	preview_5->setPiece( 5 );
	preview_6->setPiece( 6 );

	refreshState();

	connect( actionNew, SIGNAL(triggered()), this, SLOT(newGame()) );
	connect( actionScores, SIGNAL(triggered()), this, SLOT(showScores()) );

	#ifdef _DEBUG
	connect( this, SIGNAL(closed()), DebugConsole::widget(), SLOT(close()) );

	FBDialogs * dialogs = new FBDialogs( this );
	dialogs->setReferenceWidget( this );
	connect( actionMain_Window_Size, SIGNAL(triggered()), dialogs, SLOT(showSize()) );
	#else
	delete actionMain_Window_Size; actionMain_Window_Size = 0;
	delete menuDEBUG; menuDEBUG = 0;
	#endif
}

void FBMainWindow::closeEvent( QCloseEvent * e )
{
	emit closed();
	QWidget::closeEvent( e );
}

void FBMainWindow::keyPressEvent( QKeyEvent * e )
{
	switch( e->key() )
	{
	case Qt::Key_Up:
	case Qt::Key_W:
		game()->rotateRight();
		e->accept();
		break;

	case Qt::Key_Down:
	case Qt::Key_S:
		game()->advance();
		e->accept();
		break;

	case Qt::Key_Left:
	case Qt::Key_A:
		game()->moveLeft();
		e->accept();
		break;

	case Qt::Key_Right:
	case Qt::Key_D:
		game()->moveRight();
		e->accept();
		break;

	case Qt::Key_Space:
	case Qt::Key_X:
		game()->drop();
		break;

	case Qt::Key_P:
		if( mTimer->isActive() ) mTimer->stop();
		else mTimer->start();
		e->accept();
		break;

	default:
		QMainWindow::keyPressEvent( e );
	}

	if( e->isAccepted() )
		refreshState();
}

void FBMainWindow::tick()
{
	game()->advance();
	refreshState();
	if( game()->gameOver() )
	{
		QString msg;
		mTimer->stop();
		if( game()->score() > game()->highScore(9).score )
		{
			QDialog new_highscore( this );
			Ui::highscore_dlg ui;

			ui.setupUi( &new_highscore );
			ui.new_score->setText( QString::number(game()->score()) );

			new_highscore.exec();

			HighScore score;
			score.name = qPrintable(ui.new_name->text().trimmed());
			score.score = game()->score();
			game()->setHighScore( 9, score );
			showScores();
		}
		game()->saveHighScores();
	}
	if( game()->levelChanged() )
		mTimer->setInterval( std::max<int>(125, 800 - game()->level() * 75) );
}

void FBMainWindow::newGame()
{
	game()->newGame( (rand() % 10000 == 0) );
	mTimer->setInterval( std::max<int>(125, 800 - game()->level() * 75) );
	mTimer->start();
	refreshState();
}

void FBMainWindow::showScores()
{
	QDialog scores_dlg( this );
	Ui::scores_dlg ui;

	ui.setupUi( &scores_dlg );

	ui.name_1->setText( game()->highScore(0).name.c_str() );
	ui.name_2->setText( game()->highScore(1).name.c_str() );
	ui.name_3->setText( game()->highScore(2).name.c_str() );
	ui.name_4->setText( game()->highScore(3).name.c_str() );
	ui.name_5->setText( game()->highScore(4).name.c_str() );
	ui.name_6->setText( game()->highScore(5).name.c_str() );
	ui.name_7->setText( game()->highScore(6).name.c_str() );
	ui.name_8->setText( game()->highScore(7).name.c_str() );
	ui.name_9->setText( game()->highScore(8).name.c_str() );
	ui.name_10->setText( game()->highScore(9).name.c_str() );

	ui.score_1->setText( QString::number(game()->highScore(0).score) );
	ui.score_2->setText( QString::number(game()->highScore(1).score) );
	ui.score_3->setText( QString::number(game()->highScore(2).score) );
	ui.score_4->setText( QString::number(game()->highScore(3).score) );
	ui.score_5->setText( QString::number(game()->highScore(4).score) );
	ui.score_6->setText( QString::number(game()->highScore(5).score) );
	ui.score_7->setText( QString::number(game()->highScore(6).score) );
	ui.score_8->setText( QString::number(game()->highScore(7).score) );
	ui.score_9->setText( QString::number(game()->highScore(8).score) );
	ui.score_10->setText( QString::number(game()->highScore(9).score) );

	scores_dlg.exec();
}

void FBMainWindow::refreshState()
{
	preview_next->setPiece( game()->nextPiece() ? game()->nextPiece()->type() : -1 );
	count_0->setText( QString::number(game()->pieceCount(0)) );
	count_1->setText( QString::number(game()->pieceCount(1)) );
	count_2->setText( QString::number(game()->pieceCount(2)) );
	count_3->setText( QString::number(game()->pieceCount(3)) );
	count_4->setText( QString::number(game()->pieceCount(4)) );
	count_5->setText( QString::number(game()->pieceCount(5)) );
	count_6->setText( QString::number(game()->pieceCount(6)) );
	current_level->setText( QString::number(game()->level()) );
	lines_cleared->setText( QString::number(game()->lines()) );
	current_score->setText( QString::number(game()->score()) );
	high_score->setText( QString::number(std::max<uint32_t>(game()->score(), game()->highScore(0).score)) );
	game_widget->updateGL();
	// TODO update live score, level, lines, stats display
}
